
module flash_ctrl_top(
    // APB interface
    input                               pclk_i,
    input                               prstn_i,
    input  [31:0]                       paddr_i,
    input                               penable_i,
    input                               psel_i,
    input  [2 :0]                       pprot_i,
    input  [31:0]                       pwdata_i,
    input                               pwrite_i,
    output [31:0]                       prdata_o,

    // spi interface
    input                               spi_rx_i,
    output                              spi_clk_o,
    output                              spi_tx_o,
    output                              spi_csn_o
);

wire                                  s0_pclk        ;
wire                                  s0_prstn       ;
wire [31:0]                           s0_paddr       ;
wire                                  s0_penable     ;
wire                                  s0_psel        ;
wire [2 :0]                           s0_pprot       ;
wire [31:0]                           s0_pwdata      ;
wire                                  s0_pwrite      ;
wire [31:0]                           s0_prdata      ;

wire                                  s1_pclk        ;
wire                                  s1_prstn       ;
wire [31:0]                           s1_paddr       ;
wire                                  s1_penable     ;
wire                                  s1_psel        ;
wire [2 :0]                           s1_pprot       ;
wire [31:0]                           s1_pwdata      ;
wire                                  s1_pwrite      ;
wire [31:0]                           s1_prdata      ;

wire                                  s2_pclk        ;
wire                                  s2_prstn       ;
wire [31:0]                           s2_paddr       ;
wire                                  s2_penable     ;
wire                                  s2_psel        ;
wire [2 :0]                           s2_pprot       ;
wire [31:0]                           s2_pwdata      ;
wire                                  s2_pwrite      ;
wire [31:0]                           s2_prdata      ;

wire                                  txdata_state   ;
wire                                  tx_1b_data_done;
wire                                  byte_cnt_flag  ;
wire [7:0]                            rdata_txbuf    ;

wire                                  rxdata_state   ;
wire                                  rx_1b_data_done;
wire [7:0]                            rdata_rxbuf    ;

wire                                  op_done        ;
wire                                  op_err         ;
wire [2:0]                            err_state      ;
wire [31:0]                           clk_div        ;
wire                                  clk_mode       ;
wire                                  w1B_req        ;
wire                                  r_req          ;
wire                                  r_sreg1_req    ;
wire                                  r_id_req       ;
wire                                  ce_req         ;
wire                                  se_req         ;
wire                                  be32_req       ;
wire                                  be64_req       ;
wire [31:0]                           addr_flash     ;
wire [7 :0]                           data_len       ;
spi_apb_demux u_spi_apb_demux(
    // APB interface
    .m_pclk_i               (       pclk_i          ),
    .m_prstn_i              (       prstn_i         ),
    .m_paddr_i              (       paddr_i         ),
    .m_penable_i            (       penable_i       ),
    .m_psel_i               (       psel_i          ),
    .m_pprot_i              (       pprot_i         ),
    .m_pwdata_i             (       pwdata_i        ),
    .m_pwrite_i             (       pwrite_i        ),
    .m_prdata_o             (       prdata_o        ),

    // tx_bur APB interface
    .s0_pclk_o              (       s0_pclk         ),
    .s0_prstn_o             (       s0_prstn        ),
    .s0_paddr_o             (       s0_paddr        ),
    .s0_penable_o           (       s0_penable      ),
    .s0_psel_o              (       s0_psel         ),
    .s0_pprot_o             (       s0_pprot        ),
    .s0_pwdata_o            (       s0_pwdata       ),
    .s0_pwrite_o            (       s0_pwrite       ),
    .s0_prdata_i            (       s0_prdata       ),

    // rx_bur APB interface
    .s1_pclk_o              (       s1_pclk         ),
    .s1_prstn_o             (       s1_prstn        ),
    .s1_paddr_o             (       s1_paddr        ),
    .s1_penable_o           (       s1_penable      ),
    .s1_psel_o              (       s1_psel         ),
    .s1_pprot_o             (       s1_pprot        ),
    .s1_pwdata_o            (       s1_pwdata       ),
    .s1_pwrite_o            (       s1_pwrite       ),
    .s1_prdata_i            (       s1_prdata       ),

    // ctrl_regs APB interface
    .s2_pclk_o              (       s2_pclk         ),
    .s2_prstn_o             (       s2_prstn        ),
    .s2_paddr_o             (       s2_paddr        ),
    .s2_penable_o           (       s2_penable      ),
    .s2_psel_o              (       s2_psel         ),
    .s2_pprot_o             (       s2_pprot        ),
    .s2_pwdata_o            (       s2_pwdata       ),
    .s2_pwrite_o            (       s2_pwrite       ),
    .s2_prdata_i            (       s2_prdata       )
);

spi_tx_buf u_spi_tx_buf(
    // APB interface
    .pclk_i                 (       s1_pclk         ),
    .prstn_i                (       s1_prstn        ),
    .paddr_i                (       s1_paddr        ),
    .penable_i              (       s1_penable      ),
    .psel_i                 (       s1_psel         ),
    .pprot_i                (       s1_pprot        ),
    .pwdata_i               (       s1_pwdata       ),
    .pwrite_i               (       s1_pwrite       ),
    .prdata_o               (       s1_prdata       ),

    // spi fsm ctrl
    .txdata_state_i         (       txdata_state    ),
    .tx_1b_data_done_i      (       tx_1b_data_done ),
    .byte_cnt_flag_i        (       byte_cnt_flag   ),
    .rdata_o                (       rdata_txbuf     )             
);

spi_rx_buf u_spi_rx_buf(
    // APB interface
    .pclk_i                 (       s0_pclk          ),
    .prstn_i                (       s0_prstn         ),
    .paddr_i                (       s0_paddr         ),
    .penable_i              (       s0_penable       ),
    .psel_i                 (       s0_psel          ),
    .pprot_i                (       s0_pprot         ),
    .pwdata_i               (       s0_pwdata        ),
    .pwrite_i               (       s0_pwrite        ),
    .prdata_o               (       s0_prdata        ),

    // spi fsm ctrl
    .rxdata_state_i         (       rxdata_state    ),
    .rx_1b_data_done_i      (       rx_1b_data_done ),
    .byte_cnt_flag_i        (       byte_cnt_flag   ),
    .rdata_i                (       rdata_rxbuf     )             
);

spi_ctrl_regs u_spi_ctrl_regs(
    // APB interface
    .pclk_i                 (       s2_pclk         ),
    .prstn_i                (       s2_prstn        ),
    .paddr_i                (       s2_paddr        ),
    .penable_i              (       s2_penable      ),
    .psel_i                 (       s2_psel         ),
    .pprot_i                (       s2_pprot        ),
    .pwdata_i               (       s2_pwdata       ),
    .pwrite_i               (       s2_pwrite       ),
    .prdata_o               (       s2_prdata       ),

    // state ctrl
    .rx_1b_data_done_i      (       rx_1b_data_done ),
    .op_done_i              (       op_done         ),
    .op_err_i               (       op_err          ),
    .rdata_i                (       rdata_rxbuf     ),
    .err_state_i            (       err_state       ),

    // spi 时钟配置信号
    .clk_div_o              (       clk_div         ),
    .clk_mode_o             (       clk_mode        ),

    // 页编程请求
    .w1B_req_o              (       w1B_req         ),

    // 读请求
    .r_req_o                (       r_req           ),
    .r_sreg1_req_o          (       r_sreg1_req     ),
    .r_id_req_o             (       r_id_req        ),   

    // 擦除请求
    .ce_req_o               (       ce_req          ),  
    .se_req_o               (       se_req          ),  
    .be32_req_o             (       be32_req        ),
    .be64_req_o             (       be64_req        ),

    // 传输控制信号
    .addr_o                 (       addr_flash      ),    
    .data_len_o             (       data_len        )
);

spi_fsm u_spi_fsm(
    // 20MHz
    .clk_i                  (       pclk_i          ),  
    .rstn_i                 (       prstn_i         ),     

    // spi clk config       
    .clk_div_i              (       clk_div         ),  
    .clk_mode_i             (       clk_mode        ),     

    // 页编程请求                                           8'h02
    .w1B_req_i              (       w1B_req         ),  

    // 读请求                                               8'h03
    .r_req_i                (       r_req           ),        
    .r_sreg1_req_i          (       r_sreg1_req     ),  
    .r_id_req_i             (       r_id_req        ),      

    // 擦除请求     
    .ce_req_i               (       ce_req          ),  
    .se_req_i               (       se_req          ),  
    .be32_req_i             (       be32_req        ),  
    .be64_req_i             (       be64_req        ),  

    .addr_i                 (       addr_flash      ), 
    .wdata_i                (       rdata_txbuf     ), 
    .data_len_i             (       data_len        ), 

    .tx_1b_data_done_o      (       tx_1b_data_done ), 
    .txdata_state_o         (       txdata_state    ), 
    .rx_1b_data_done_o      (       rx_1b_data_done ), 
    .rxdata_state_o         (       rxdata_state    ), 
    .byte_cnt_flag_o        (       byte_cnt_flag   ), 
    .rdata_o                (       rdata_rxbuf     ), 
    .op_done_o              (       op_done         ), 
    .op_err_o               (       op_err          ), 
    .err_state_o            (       err_state       ), 

    // spi接口信号
    .spi_rx_i               (       spi_rx_i        ),
    .spi_csn_o              (       spi_csn_o       ),
    .spi_clk_o              (       spi_clk_o       ),         
    .spi_tx_o               (       spi_tx_o        )
);
endmodule
